import jwt from 'jsonwebtoken';

import { dataGet } from '#Utils/helper.js';

import config from '#Config/app.js';



class JwtContainer {
    constructor() {
        if (JwtContainer.instance) {
            return JwtContainer.instance;
        }

        JwtContainer.instance = this;

        this._secret = '';
        this._options = {}
        this._autoRefreshGap = 120;

        this.init();
    }

    get secret() {
        return this._secret;
    }

    set secret(value) {
        this._secret = value;
    }

    get options() {
        return this._options;
    }

    set options(value) {
        this._options = value;
    }

    get autoRefreshGap() {
        return this._autoRefreshGap;
    }

    set autoRefreshGap(value) {
        this._autoRefreshGap = value;
    }

    init() {
        let jwtConfig = dataGet(config, 'jwt', {});
        this.secret = jwtConfig.secret;
        this.options = {
            expiresIn: jwtConfig.expiresIn,
            algorithm: jwtConfig.algorithm
        }
        // 120s
        this.autoRefreshGap = jwtConfig.autoRefreshGap;
    }

    sign(payload) {
        return jwt.sign(payload, this.secret, this.options);
    }

    verify(token) {
        token = this.trimToken(token);
        return jwt.verify(token, this.secret, this.options);
    }
    decode(token) {
        token = this.trimToken(token);
        return jwt.decode(token);
    }

    refresh(token) {
        let payload = this.decode(token);

        if (payload.exp - Math.floor(Date.now() / 1000) < this.autoRefreshGap) {
            delete payload.iat;
            delete payload.exp;
            delete payload.nbf;
            delete payload.jti;
            delete payload.aud;
            delete payload.iss;
            delete payload.sub;
            delete payload.typ;
            delete payload.alg;
            delete payload.kid;
            delete payload.rest;
            return this.sign(payload);
        }
        return null;
    }

    payload(token) {
        let payload = this.decode(token);
        delete payload.iat;
        delete payload.exp;
        delete payload.nbf;
        delete payload.jti;
        delete payload.aud;
        delete payload.iss;
        delete payload.sub;
        delete payload.typ;
        delete payload.alg;
        delete payload.kid;
        delete payload.rest;
        return payload;
    }

    trimToken(token) {
        token = token.split(' ');
        if (token.length > 1) {
            return token[1];
        }
        return token[0];
    }
}

export default new JwtContainer();